﻿using System;
using System.Collections.Generic;
using System.Linq;
using MarriageFertility.DataType;
using MarriageFertility.Extensions;
using MarriageFertility.Helpers;
using MarriageFertility.Mcm;
using MarriageFertility.Models;
using MarriageFertility.Notifications;
using MarriageFertility.Texts;
using TaleWorlds.CampaignSystem;
using TaleWorlds.CampaignSystem.Actions;
using TaleWorlds.CampaignSystem.CharacterDevelopment;
using TaleWorlds.CampaignSystem.Party;
using TaleWorlds.Core;
using TaleWorlds.Localization;

namespace MarriageFertility.Dialogs
{
    public static class NtrDialog
    {
        private static readonly int BaseHireCost = 5000;
        private static int _negotiationAttempts = 0;
        private static Hero _lord;
        private static Hero _wife;
        private static bool _isShow;
        public static List<NtrRelation> NtrWifeList = new();
        private static bool _persuasionSuccess; // Track persuasion outcome

        public static void AddDialogs(CampaignGameStarter campaignGameStarter)
        {
            // 玩家发起妻子租赁请求
            campaignGameStarter.AddPlayerLine("ntr_wife_hero_request", "hero_main_options", "ntr_wife_to_lord",
                NtrText.WifeHeroRequestText.ToString(), HasWife, () =>
                {
                    _wife = null;
                    _isShow = false;
                });

            // 贵族回应租赁请求
            campaignGameStarter.AddDialogLine("ntr_wife_hero_response", "ntr_wife_to_lord", "ask_player_ntr_wife",
                NtrText.WifeHeroResponseText.ToString(), null, null);

            // 玩家选择妻子
            campaignGameStarter.AddPlayerLine("ntr_wife_choose_wife", "ask_player_ntr_wife", "choose_one_ntr_wife",
                "{=!}{RESPONSE_CHOOSE_WIFE}", () =>
                {
                    if (_wife != null)
                    {
                        MBTextManager.SetTextVariable("RESPONSE_CHOOSE_WIFE", NtrText.WifeChooseWifeText.SetTextVariable("wife", _wife.Name));
                    }
                    else
                    {
                        MBTextManager.SetTextVariable("RESPONSE_CHOOSE_WIFE", NtrText.WifeChooseWifeText);
                    }
                    return true;
                }, () => ShowWife());

            // 贵族接受妻子并支付费用
            campaignGameStarter.AddDialogLine("lord_accept_your_wife", "choose_one_ntr_wife", "hero_main_options",
                "{=!}{RESPONSE_ACCEPT_WIFE}", () =>
                {
                    if (_wife != null && CanLordAcceptWife())
                    {
                        MBTextManager.SetTextVariable("RESPONSE_ACCEPT_WIFE", NtrText.LordAcceptYourWifeText.SetTextVariable("wife", _wife.Name));
                        return true;
                    }
                    return false;
                }, GetNgradientGold);
            
            
            campaignGameStarter.AddDialogLine("lord_reject_wife", "choose_one_ntr_wife", "negotiate_ntr_wife",
                "{=!}{RESPONSE_REJECT_WIFE}", () =>
                {
                    if (_wife != null && !CanLordAcceptWife())
                    {
                        TextObject rejectionMessage;
                        int lordHonor = _lord.GetTraitLevel(DefaultTraits.Honor);
                        int lordGold = _lord.PartyBelongedTo?.LeaderHero?.Gold ?? 0;
                        int hireCost = CalculateHireCost(_wife);

                        if (lordHonor > 1)
                        {
                            rejectionMessage = new TextObject("{=MF_LordRejectWifeHonor}I find this proposal distasteful and beneath my honor.");
                        }
                        else if (lordGold < hireCost)
                        {
                            rejectionMessage = new TextObject("{=MF_LordRejectWifeGold}I lack the coin to entertain such an arrangement.");
                        }
                        else
                        {
                            rejectionMessage = new TextObject("{=MF_LordRejectWifeGeneric}I'm not interested in your offer.");
                        }

                        MBTextManager.SetTextVariable("RESPONSE_REJECT_WIFE", rejectionMessage);
                        return true;
                    }
                    return false;
                }, () =>
                {
                    // 应用关系惩罚并提示
                    ChangeRelationAction.ApplyPlayerRelation(_lord, -2);
                    MBInformationManager.AddQuickInformation(new TextObject("{=MF_LordRejectionPenalty}Your proposal has slightly strained relations with {lord}.")
                        .SetTextVariable("lord", _lord.Name));
                    _negotiationAttempts = 0; // 重置谈判次数
                });

            // 玩家拒绝租赁妻子
            campaignGameStarter.AddPlayerLine("ntr_wife_refuse_offer", "ask_player_ntr_wife", "hero_main_options",
                NtrText.WifeRefuseOfferText.ToString(), () => _wife == null || true, RefuseOffer);
            
            // 贵族回应玩家的拒绝
            campaignGameStarter.AddDialogLine("lord_refuse_response", "negotiate_ntr_wife", "negotiate_ntr_options",
                NtrText.LordRefuseResponseText.ToString(), () => _wife != null && !CanLordAcceptWife(), null);

            // 谈判选项1
            campaignGameStarter.AddPlayerLine("negotiate_option_1", "negotiate_ntr_options", "negotiate_result_1",
                NtrText.NegotiateOption1.ToString(), NegotiateCondition1, NegotiateOption1);

            campaignGameStarter.AddDialogLine("negotiate_result_1", "negotiate_result_1", "hero_main_options",
                NtrText.NegotiateResult1.ToString(), null, null);

            // 谈判选项2
            campaignGameStarter.AddPlayerLine("negotiate_option_2", "negotiate_ntr_options", "negotiate_result_2",
                NtrText.NegotiateOption2.ToString(), NegotiateCondition2, NegotiateOption2);

            campaignGameStarter.AddDialogLine("negotiate_result_2", "negotiate_result_2", "hero_main_options",
                NtrText.NegotiateResult2.ToString(), null, null);

            // 谈判选项3
            campaignGameStarter.AddPlayerLine("negotiate_option_3", "negotiate_ntr_options", "negotiate_result_3",
                NtrText.NegotiateOption3.ToString(), NegotiateCondition3, NegotiateOption3);

            campaignGameStarter.AddDialogLine("negotiate_result_3", "negotiate_result_3", "hero_main_options",
                NtrText.NegotiateResult3.ToString(), null, null);

            // 谈判选项：请求恩惠
            campaignGameStarter.AddPlayerLine("negotiate_option_favor", "negotiate_ntr_options", "negotiate_result_favor",
                NtrText.NegotiateFavor.ToString(), NegotiateConditionFavor, NegotiateOptionFavor);

            campaignGameStarter.AddDialogLine("negotiate_result_favor", "negotiate_result_favor", "hero_main_options",
                NtrText.NegotiateFavorResult.ToString(), null, null);

            // 玩家选择退出谈判
            campaignGameStarter.AddPlayerLine("negotiate_option_decline", "negotiate_ntr_options", "hero_main_options",
                NtrText.NegotiateDecline.ToString(), () => _wife != null, DeclineNegotiation);

            // 检查妻子状态
            campaignGameStarter.AddPlayerLine("ntr_wife_check_condition", "hero_main_options", "ntr_wife_condition_response",
                "{=!}{RESPONSE_CONDITION}", HasWifeWithLordForCondition, null);

            campaignGameStarter.AddDialogLine("ntr_wife_condition_response", "ntr_wife_condition_response", "hero_main_options",
                "{=!}{RESPONSE_RESPONSE}", () =>
                {
                    _lord = Hero.OneToOneConversationHero;
                    _wife = NtrWifeList.FirstOrDefault(r => r.Lord == _lord && Hero.MainHero.IsWife(r.Wife))?.Wife;
                    if (_wife != null)
                    {
                        MBTextManager.SetTextVariable("RESPONSE_RESPONSE", NtrText.WifeConditionResponseText.SetTextVariable("wife", _wife.Name));
                        return true;
                    }
                    return false;
                }, ReportWifeCondition);

            // 请求妻子返回
            campaignGameStarter.AddPlayerLine("ntr_wife_request_return", "hero_main_options", "ntr_wife_return_response",
                "{=!}{RESPONSE_NTR}", () =>
                {
                    bool hasWife = HasWifeWithLord();
                    if (hasWife && _wife != null)
                    {
                        MBTextManager.SetTextVariable("RESPONSE_NTR", NtrText.WifeRequestReturnText.SetTextVariable("wife", _wife.Name));
                    }
                    return hasWife;
                }, null);

            campaignGameStarter.AddDialogLine("ntr_wife_return_response", "ntr_wife_return_response", "hero_main_options",
                "{=!}{RESPONSE_RETURN_RESPONSE}", () =>
                {
                    _lord = Hero.OneToOneConversationHero;
                    _wife = NtrWifeList.FirstOrDefault(r => r.Lord == _lord && Hero.MainHero.IsWife(r.Wife))?.Wife;
                    if (_wife != null)
                    {
                        MBTextManager.SetTextVariable("RESPONSE_RETURN_RESPONSE", NtrText.WifeReturnResponseText.SetTextVariable("wife", _wife.Name));
                        return true;
                    }
                    return false;
                }, RequestWifeReturn);

            // 说服贵族
            campaignGameStarter.AddPlayerLine("ntr_wife_persuade_lord", "hero_main_options", "ntr_wife_persuade_response",
                "{=!}{RESPONSE_PERSUADE}", () =>
                {
                    bool canPersuade = CanPersuadeLord();
                    if (canPersuade && _wife != null)
                    {
                        MBTextManager.SetTextVariable("RESPONSE_PERSUADE", NtrText.WifePersuadeLordText.SetTextVariable("wife", _wife.Name));
                    }
                    return canPersuade;
                }, PersuadeLord);

            campaignGameStarter.AddDialogLine("ntr_wife_persuade_response", "ntr_wife_persuade_response", "hero_main_options",
                "{=!}{RESPONSE_PERSUADE_RESPONSE}", () =>
                {
                    _lord = Hero.OneToOneConversationHero;
                    _wife = NtrWifeList.FirstOrDefault(r => r.Lord == _lord && Hero.MainHero.IsWife(r.Wife))?.Wife;
                    if (_wife != null && _lord != null)
                    {
                        var relation = NtrWifeList.FirstOrDefault(r => r.Lord == _lord && r.Wife == _wife);
                        if (relation == null) return false;

                        TextObject message;
                        if (relation.LordLikesWife)
                        {
                            message = NtrText.PersuadeLordAlreadyLikes;
                        }
                        else if (_persuasionSuccess)
                        {
                            message = NtrText.PersuadeLordSuccess;
                        }
                        else
                        {
                            message = NtrText.PersuadeLordFailure;
                        }
                        message.SetTextVariable("lord", _lord.Name);
                        message.SetTextVariable("wife", _wife.Name);
                        MBTextManager.SetTextVariable("RESPONSE_PERSUADE_RESPONSE", message);
                        return true;
                    }
                    return false;
                }, null);
        }

        private static bool HasWife()
        {
            return MCMSettings.Instance.EnableRentWifeDialog &&
                   Hero.OneToOneConversationHero != null &&
                   Hero.MainHero.WifeInParty() &&
                   Hero.OneToOneConversationHero.PartyBelongedTo?.MemberRoster != null &&
                   MobileParty.MainParty?.MemberRoster != null;
        }

        private static bool HasWifeWithLord()
        {
            bool hasWife = MCMSettings.Instance.EnableRentWifeDialog &&
                           Hero.OneToOneConversationHero is { IsLord: true, IsFemale: false } hero &&
                           NtrWifeList.Any(r => r.Lord == hero && Hero.MainHero.IsWife(r.Wife) && r.Wife.PartyBelongedTo == hero.PartyBelongedTo);
            if (hasWife)
            {
                _lord = Hero.OneToOneConversationHero;
                _wife = NtrWifeList.FirstOrDefault(r => r.Lord == _lord && Hero.MainHero.IsWife(r.Wife))?.Wife;
            }
            return hasWife;
        }

        private static bool HasWifeWithLordForCondition()
        {
            var hero = Hero.OneToOneConversationHero;
            if (hero == null) return false;

            var wifeRecord = NtrWifeList.Find(r => r.Lord == hero && Hero.MainHero.IsWife(r.Wife) && r.Wife.PartyBelongedTo == hero.PartyBelongedTo);
            if (wifeRecord != null)
            {
                MBTextManager.SetTextVariable("RESPONSE_CONDITION", NtrText.WifeCheckConditionText.SetTextVariable("wife", wifeRecord.Wife.Name));
                return true;
            }
            return false;
        }

        private static bool HasWifeWithLordAndCharm()
        {
            return HasWifeWithLord() && Hero.MainHero.GetSkillValue(DefaultSkills.Charm) > 100;
        }
        
        private static bool CanLordAcceptWife()
        {
            if (_wife == null || _lord == null) return false;
            
            float playerRelation = _lord.GetRelationWithPlayer();
            int lordHonor = _lord.GetTraitLevel(DefaultTraits.Honor);
            int wifeCharm = _wife.GetSkillValue(DefaultSkills.Charm);
            int hireCost = CalculateHireCost(_wife);
            int lordGold = _lord.PartyBelongedTo?.LeaderHero?.Gold ?? 0;
            
            float acceptanceChance = 0.5f; 
            
            acceptanceChance += playerRelation / 200f;
            
            acceptanceChance += wifeCharm / 1000f;
            
            acceptanceChance -= lordHonor * 0.1f;
            
            if (lordGold < hireCost)
            {
                acceptanceChance -= 0.3f; 
            }
            
            acceptanceChance = Math.Max(0f, Math.Min(0.95f, acceptanceChance));
            
            return MBRandom.RandomFloat < acceptanceChance;
        }

        private static bool CanPersuadeLord()
        {
            bool hasWifeAndCharm = HasWifeWithLordAndCharm();
            if (!hasWifeAndCharm || _wife == null) return false;

            var relation = NtrWifeList.FirstOrDefault(r => r.Lord == _lord && r.Wife == _wife);
            return relation != null && !relation.LordLikesWife; // Only allow persuasion if lord doesn't already like wife
        }

        private static bool ShowWife()
        {
            if (Hero.OneToOneConversationHero is { } hero && !_isShow)
            {
                _lord = hero;
                var inquiryElements = GetWifeList();
                MBInformationManager.ShowMultiSelectionInquiry(
                    new MultiSelectionInquiryData(
                        NtrText.RentOutWifeTitle.ToString(),
                        NtrText.ChooseWife.ToString(),
                        inquiryElements,
                        true,
                        1, 1,
                        CommonText.Confirm,
                        CommonText.Cancel,
                        NtrToLord,
                        CancelWifeSelection), // 添加取消回调
                    true);
            }
            _isShow = true;
            return true; 
        }
        
        private static void CancelWifeSelection(List<InquiryElement> elements)
        {
            _wife = null;
            _isShow = false;
            MBInformationManager.AddQuickInformation(NtrText.PlayerRefusedOffer);
        }

        private static List<InquiryElement> GetWifeList() =>
            Hero.MainHero.Clan.Heroes
                .Where(wife => wife.IsAlive && Hero.MainHero.IsWife(wife) &&
                               MobileParty.MainParty.MemberRoster.Contains(wife.CharacterObject))
                .Select(wife => new InquiryElement(wife, wife.Name.ToString(),
                    new ImageIdentifier(CharacterCode.CreateFrom(wife.CharacterObject))))
                .ToList();

        private static void NtrToLord(List<InquiryElement> elements)
        {
            if (elements.FirstOrDefault()?.Identifier is not Hero wife) return;
            _wife = wife;
            ChangeRelationAction.ApplyPlayerRelation(wife, -10);
            ChangeRelationAction.ApplyRelationChangeBetweenHeroes(wife, _lord, 10);
            NtrWifeList.Add(new NtrRelation(_lord, wife, CampaignTime.Now));
            Hero.MainHero.PartyBelongedTo.MemberRoster.AddToCounts(wife.CharacterObject, -1);
            _lord.PartyBelongedTo.MemberRoster.AddToCounts(wife.CharacterObject, 1);
            ApplyReputationPenalty();

            if (RelationHelper.HotButterFound)
            {
                MBInformationManager.ShowSceneNotification(new HotButterNotification(_lord, _wife, _lord.CurrentSettlement, Hero.MainHero));
            }
        }

        private static void ApplyReputationPenalty()
        {
            Hero.MainHero.Clan.Renown -= 5f;
            MBInformationManager.AddQuickInformation(NtrText.ReputationPenalty);
        }

        private static void GetNgradientGold()
        {
            if (_wife == null) return;
            int gold = CalculateHireCost(_wife);
            GiveGoldAction.ApplyBetweenCharacters(null, Hero.MainHero, gold);
        }

        private static void RefuseOffer()
        {
            _wife = null;
            _isShow = false;
            MBInformationManager.AddQuickInformation(NtrText.PlayerRefusedOffer);
        }

        private static void DeclineNegotiation()
        {
            MBInformationManager.AddQuickInformation(NtrText.NegotiateDeclineMessage);
        }

        private static void ReportWifeCondition()
        {
            var relation = NtrWifeList.FirstOrDefault(r => r.Lord == _lord && r.Wife == _wife);
            if (relation == null) return;

            var message = relation.WifeMood > 70f ? NtrText.WifeConditionGood :
                          relation.WifeMood > 30f ? NtrText.WifeConditionNeutral :
                          NtrText.WifeConditionPoor;
            message.SetTextVariable("wife", _wife.Name);
            MBInformationManager.AddQuickInformation(message);

            if (relation.WifeLoyalty < 20f)
            {
                var loyaltyMessage = NtrText.WifeLowLoyaltyWarning;
                loyaltyMessage.SetTextVariable("wife", _wife.Name);
                MBInformationManager.AddQuickInformation(loyaltyMessage);
            }
        }

        private static void RequestWifeReturn()
        {
            var relation = NtrWifeList.FirstOrDefault(r => r.Lord == _lord && r.Wife == _wife);
            if (relation == null) return;

            float returnChance = Hero.MainHero.GetSkillValue(DefaultSkills.Charm) / 300f + _lord.GetRelationWithPlayer() / 100f;
            if (MBRandom.RandomFloat < returnChance)
            {
                _wife.PartyBelongedTo.MemberRoster.AddToCounts(_wife.CharacterObject, -1);
                MobileParty.MainParty.MemberRoster.AddToCounts(_wife.CharacterObject, 1);
                NtrWifeList.Remove(relation);
                ChangeRelationAction.ApplyPlayerRelation(_wife, -5);
                ChangeRelationAction.ApplyPlayerRelation(_lord, -10);
                Hero.MainHero.Clan.Renown -= 2f;

                var successMessage = NtrText.WifeReturnSuccess;
                successMessage.SetTextVariable("wife", _wife.Name);
                MBInformationManager.AddQuickInformation(successMessage);
            }
            else
            {
                ChangeRelationAction.ApplyPlayerRelation(_lord, -5);
                var failMessage = NtrText.WifeReturnFailure;
                failMessage.SetTextVariable("lord", _lord.Name);
                failMessage.SetTextVariable("wife", _wife.Name);
                MBInformationManager.AddQuickInformation(failMessage);
            }
        }
        
        private static void PersuadeLord()
        {
            var relation = NtrWifeList.FirstOrDefault(r => r.Lord == _lord && r.Wife == _wife);
            if (relation == null) return;
            
            float persuadeChance = Hero.MainHero.GetSkillValue(DefaultSkills.Charm) / 400f;
            int honorLevel = _lord.GetTraitLevel(DefaultTraits.Honor);
            persuadeChance -= honorLevel * 0.05f; 

            _persuasionSuccess = MBRandom.RandomFloat < persuadeChance;
            if (_persuasionSuccess)
            {
                relation.LordLikesWife = true;
                ChangeRelationAction.ApplyPlayerRelation(_lord, 5);
            }
            else
            {
                ChangeRelationAction.ApplyPlayerRelation(_lord, -3);
            }
        }

        private static bool NegotiateCondition1() => NegotiateCondition(20);
        private static bool NegotiateCondition2() => NegotiateCondition(40);
        private static bool NegotiateCondition3() => NegotiateCondition(60);
        private static bool NegotiateConditionFavor() => NegotiateCondition(50) && Hero.MainHero.GetSkillValue(DefaultSkills.Charm) > 150;

        private static bool NegotiateCondition(int relationThreshold)
        {
            if (_wife == null || CanLordAcceptWife()) return false; // 确保只有在领主拒绝时才能谈判
            bool result = Hero.OneToOneConversationHero != null &&
                          Hero.OneToOneConversationHero.GetRelationWithPlayer() + relationThreshold > 10 &&
                          MBRandom.RandomFloat < (Hero.MainHero.GetSkillValue(DefaultSkills.Trade) / 200f + 0.3f);
            if (!result)
            {
                MBInformationManager.AddQuickInformation(new TextObject($"调试: 谈判条件未满足 (关系值: {Hero.OneToOneConversationHero?.GetRelationWithPlayer()}, 贸易技能: {Hero.MainHero.GetSkillValue(DefaultSkills.Trade)})"));
            }
            return result;
        }

        private static void NegotiateOption1()
        {
            _negotiationAttempts++;
            if (_negotiationAttempts == 1)
            {
                int gold = (int)(CalculateHireCost(_wife) * 0.8f);
                GiveGoldAction.ApplyBetweenCharacters(null, Hero.MainHero, gold);
                MBInformationManager.AddQuickInformation(NtrText.NegotiateSuccess);
            }
            else
            {
                MBInformationManager.AddQuickInformation(NtrText.NegotiateFail);
            }
        }

        private static void NegotiateOption2()
        {
            _negotiationAttempts++;
            if (_negotiationAttempts == 2)
            {
                int gold = CalculateHireCost(_wife) / 2;
                GiveGoldAction.ApplyBetweenCharacters(null, Hero.MainHero, gold);
                MBInformationManager.AddQuickInformation(NtrText.NegotiateSuccess);
            }
            else
            {
                MBInformationManager.AddQuickInformation(NtrText.NegotiateFail);
            }
        }

        private static void NegotiateOption3()
        {
            _negotiationAttempts++;
            if (_negotiationAttempts == 3)
            {
                int gold = CalculateHireCost(_wife) / 5;
                GiveGoldAction.ApplyBetweenCharacters(null, Hero.MainHero, gold);
                MBInformationManager.AddQuickInformation(NtrText.NegotiateSuccess);
            }
            else
            {
                MBInformationManager.AddQuickInformation(NtrText.NegotiateFail);
            }
        }

        private static void NegotiateOptionFavor()
        {
            _negotiationAttempts++;
            if (_negotiationAttempts == 1)
            {
                ChangeRelationAction.ApplyPlayerRelation(_lord, 15);
                MBInformationManager.AddQuickInformation(NtrText.NegotiateSuccess);
            }
            else
            {
                MBInformationManager.AddQuickInformation(NtrText.NegotiateFail);
            }
        }

        private static int GetTotalSkillValue(Hero hero)
        {
            int totalSkillPoints = 0;
            foreach (var skill in CharacterDefinitions.DefaultAllSkills)
            {
                totalSkillPoints += hero.GetSkillValue(skill);
            }
            return totalSkillPoints;
        }

        private static int CalculateHireCost(Hero hero)
        {
            int baseCost = BaseHireCost + CalculateCostFromSkills(GetTotalSkillValue(hero));
            var relation = NtrWifeList.Find(r => r.Wife == hero && r.Lord == _lord);
            return relation?.LordLikesWife == true ? (int)(baseCost * 1.5f) : baseCost;
        }

        private static int CalculateCostFromSkills(int totalSkillPoints) =>
            totalSkillPoints switch
            {
                < 300 => totalSkillPoints * 10,
                < 1024 => 3000 + (totalSkillPoints - 300) * 50,
                _ => 100000 + (totalSkillPoints - 1024) * 100
            };
    }
}